home *** CD-ROM | disk | FTP | other *** search
-
- I notices that the Delphi FAQ has not been updated in over a year. Since much
- of the information needed to write Delphi components is undocumented I thought
- that maybe there should be a component writing FAQ.
-
- I have been going through some of my source code to get some of the tricks
- that I have had to use in writing components. I am going through my mail to
- see what tricks people have sent me and I will attempt to give credit to those
- who have mailed me information.
-
- Right now this document is short but hopefully it will grow over time. Some
- of the information enclose has never been published. If you have
- something to contribute or suggestions then mail them to me.
-
- So hear goes......
-
-
- The Unofficial Delphi Component Writing FAQ
-
- Maintainer: John M. Miano miano@worldnet.att.net
- Version: 1
- Last Updated: 30-Aug-96
-
- ------------------------------------------------------------------------
- Table of Contents
-
- Section 1 - Introduction
- 1.1. What is the purpose of this document?
-
- Section 2 - IDE
- 2.1. How can I locate problems the result when my component is used in the
- IDE?
- 2.2. How do I view assembly langugage the Delphi Generates?
- 2.3. I can create my control at run time but it crashes at design time. What
- is wrong?
- 2.4. How can I make my control work only in design mode?
-
- Section 3 - Using other components within a component
- 3.1. How can I add a scroll bar component to my component and have it work at
- in design mode?
- 3.2. How do I create a Windows '95-style scroll bar?
-
- Section 4 - Bound Controls
- 4.1. Where is the documentation for the TDataLink class?
-
- Section 5 - VCL
- 5.1. How can I step through the VCL source while debugging
-
- Section 6 - Other Sources of Information
- 6.1. Are there any books one how to write Delphi components?
-
- Section 7 - Persistant Objects
- 7.1. How can I save a complex object containing child objects to the .DFM
- file.
-
- ------------------------------------------------------------------------
- Section 1 - Introductions
-
- 1.1. What is the purpose of this document?
-
- The purpose of this document is to answer common or undocumented questions
- related to writing Delphi components. This information is provided as is.
- There are no guarentee as to its correctness. If you find error or ommissions
- sent them to the author.
-
- This document is rather short at the moment but hopefully it will grow over
- time.
-
- ------------------------------------------------------------------------
- Section 2 - IDE Problems
-
- 2.1. How can I locate problems the result when my component is used in the
- IDE?
-
- The only solution to locating problems I have found it to:
-
- 1. In Delphi go to Tools/Options then go to the "Library" page.
- Check the "Compile With Debug Info" box.
- 2. Rebuild the library.
- 3. Run Delphi from within Turbo Debugger.
-
- If you get a GPF you can use view the stack and get some idea where the
- problem is occuring.
-
- 2.2. How do I view assembly langugage the Delphi Generates?
-
- From Glen Boyd
-
- Borland/Delphi/2.0/Debugging add a string value called EnableCPU and set
- its string value to 1. This add the CPU window to the view menu. The CPU
- window is
- active at run time for stepping through and stuff like that.
-
- 2.3. I can create my control at run time but it crashes at design time. What
- is wrong?
-
- 1. You component must descent from TComponent
-
- 2. Your constructory and destructor declarations must look like:
-
- Constructor Create (AOwner : TComponent) ; Override ;
- Destructor Destroy ; Override ;
-
- 3 You will get an Access Violation/GPF if you component has any published
- properties that do not have a property editor defined. These include array
- properties and properties of types you create.
-
- How do I make a component work only in design mode?
-
- The trick is to use the Register function. This is only called in design
- mode. You can
- use it to set a flag that your constructors can check.
-
- 2.4. How can I make my control work only in design mode?
-
- The Register procedure is only called in design mode. You can define a flag
- in your module and have your register procedure set that flag. If that flag
- is clear in your constructor then you are not in design mode.
-
- ------------------------------------------------------------------------
- Section 3 - Using other components within a component
-
- 3.1. How can I add a scroll bar component to my component and have it work at
- in design mode?
-
- You need to define your own scroll bar class that intercepts the
- CM_DESIGNHITTEST message.
-
- TMyScrollBar = class (TScrollBar)
- Procedure CMDesignHitTest (var Message : TCMDesignHitTest) ; Message
- CM_DESIGNHITTEST ;
- End ;
-
- Procedure TMyScrollBar.CMDesignHitTest (var Message : TCMDesignHitTest) ;
- Begin
- Message.Result := 1 ;
- End ;
-
- When your component creates one of these scroll bars it needs to use
-
- TMyScrollBar.Create (Nil)
-
- rather then
-
- TMyScrollBar.Create (Self)
-
- otherwise the scroll bar will display sizing handles when it is click. This
- means you need to be sure to explicitly free the scroll bar in your
- component's destructor.
-
- 3.2 How do I create a Windows '95-style scroll bar?
-
- You need to set the page size for the scroll bar. The following code
- sequence
- illustrates this:
-
- Procedure SetPageSize (ScrollBar : TScrollBar ; PageSize : Integer) ;
- Var
- ScrollInfo : TScrollInfo ;
- Begin
- ScrollInfo.cbSize := Sizeof (ScrollInfo) ;
- ScrollInfo.fMask := SIF_PAGE ;
- ScrollInfo.nPage := PageSize ;
- SetScrollInfo (ScrollBar.Handle, SB_CTL, ScrollInfo, True) ;
- End ;
-
- To retrieve the page size use:
-
- Function GetpageSize (ScrollBar : TScrollBar) ;
- Var
- ScrollInfo : TScrollInfo ;
- Begin
- If HandleAllocated Then
- Begin
- ScrollInfo.cbSize := Sizeof (ScrollInfo) ;
- ScrollInfo.fMask := SIF_PAGE ;
- GetScrollInfo (ScrollBar.Handle, SB_CTL, ScrollInfo) ;
- Result := ScrollInfo.nPage ;
- End ;
-
- ------------------------------------------------------------------------
- Section 4 - Bound Controls
-
- 4.1. Where is the documentation for the TDataLink class?
-
- As far as I can tell the only documentation for TDataLink that exists in the
- entire universe is what follows
-
- Properties:
- ===========
-
- Property: Active : Boolean (Read Only)
- ----------------------------------------
-
- Returns true when the data link is connected to an active datasource.
- The ActiveChanged method is called to give notification when the state
- changes.
-
- Property: ActiveRecord: (Read/Write)
- --------------------------------------
-
- This sets or returns the current record within the TDatalink's buffer window.
- Valid values are
- 0..BufferCount - 1. There appear to be no range checks so assigning values
- outside this range produces unpredictable results.
-
- Property: BufferCount: (Read/Write)
- -------------------------------------
-
- The TDataLink maintains a window of records into the dataset This property is
- the size of this window and determines the maximum number of row that can be
- view simultaneously. For most controls you would use a BufferCount of one.
- For controls such as a data grid this value is the number of visible rows.
-
- Property: DataSet: TDataSet (Read)
- ------------------------------------
-
- The dataset the TDataLink is attached to. This is a shortcut to
- DataSource.DataSet.
-
- Property: DataSource: TDataSource (Read/Write)
- ------------------------------------------------
-
- Sets or returns data source control the TDataLink is attached to.
-
- Property: DataSourceFixed: Boolean (Read/WRite)
- -------------------------------------------------
-
- This property is used to prevent the data source for the TDataLink from being
- changed. If this property is set to Trye then assigning a value to the
- DataSource property will result in an exception.
-
- Property: Editing: Boolean (Read Only)
- ----------------------------------------
-
- Returns true if the datalink is in edit mode.
-
- Property: ReadOnly: Boolean (read/Write)
- ------------------------------------------
-
- This property determines if the TDataLink is read only. It does not appear to
- affect the attached datalink
- or dataset. If this property is set to True the datalink will not go into
- edit mode.
-
- Property: RecordCount: Integer (Read)
- ---------------------------------------
-
- The property returns the approximate number of records in the attached
- dataset.
-
- Methods:
- ========
-
- function Edit: Boolean;
- -----------------------
-
- Puts the TDatalink's attached dataset into edit mode.
-
- Return Value:
- True => Success
- False => Failure
-
- procedure UpdateRecord;
- -----------------------
-
- It appears that this is a function that is intended to be called by other
- parts of the data base interface and should not be called directly. All it
- does is set a flag and call UpdateData (described below).
-
-
- Virtual Methods
- ===============
-
- The mechanism for having the TDataLink object communicate with a component is
- to override these procedures.
-
- procedure ActiveChanged
- ------------------------
-
- This procedure is called whenever the datasource the TDataLink is attached to
- becomes active or
- inactive. Use the Active property to determine whether or not the link is
- active.
-
- procedure CheckBrowseMode
- -------------------------
-
- This method appears to get called before any changes take place to the
- database.
-
- procedure DataSetChanged;
- -------------------------
-
- This procedure gets called when the following events occur:
-
- o Moving to the start of the dataset
- o Moving to the end of the dataset
- o Inserting or Appending to the dataset
- o Deleting a record from the dataset
- o Canceling the editing of a record
- o Updating a record
-
- The non-overrident action for this procedure is to call
- RecordChanged (Nil)
-
- procedure DataSetScrolled(Distance: Integer)
- --------------------------------------------
-
- This procedure is called whenever the current record in the dataset changes.
- The Distance parameter tells how far the buffer window into the dataset was
- scrolled (This seems to always be in the range -1, 0, 1).
-
- Use the ActiveRecord to determine which record within the buffer window is the
- current one.
-
- It is not possible to force a scroll of the buffer window.
-
- procedure FocusControl(Field: TFieldRef)
- ----------------------------------------
-
- This appears to get called as a result of Field.FocusControl.
-
- procedure EditingChanged
- -------------------------
-
- This procedure is called when the editing state of the TDataLink changes. Use
- the Editing property to determine if the TDataLink is in edit mode or not.
-
- procedure LayoutChanged
- -----------------------
-
- This procedure is called when the layout of the attached dataset changes (e.g.
- column added) .
-
- procedure RecordChanged(Field: TField)
- --------------------------------------
-
- This procedure gets called when:
-
- o The current record is edited
- o The record's text has changed
-
- If the Field parameter is non-nil then the change occured to the specified
- field.
-
- procedure UpdateData
- --------------------
-
- This procedure is called immediately before a record is updated in the
- database. You can call the Abort procedure to prevent the record from being
- updated.
-
-
- ------------------------------------------------------------------------
- Section 5 - VCL
- 5.1. How can I step through the VCL source while debugging
-
- Copy the VCL source modules you are interested in stepping through to your
- project directory then rebuild the VCL library. You will then be able to step
- through the VCL source modules.
-
- ------------------------------------------------------------------------
- Section 6 - Other Sources of Information
-
- 6.1. Are there any books one how to write Delphi components?
-
- I have seen a couple out there but the only one I can recommend is
-
- "Developing Delphi Components" by Ray Konopka
-
- ------------------------------------------------------------------------
- Section 7 - Persistant Objects
-
- 7.1. How can I save a complex object containing child objects to the .DFM
- file.
-
- I have tried all sorts of schemes using DefineProperties and WriteComponents
- and they all failed to work. As far as I can the only way to do this is to use
- Delphi's default mechanism to store your child objects.
-
- A sequence that does work for saving to a stream is:
-
- 1. Make all of the classes whose objects you want to save descent from
- TComponent.
- 2. Make all of the values you want to save published.
- 3. Within your Register procedure add a call to RegisterComponents containing
- all of the classes you wish to store.
- 4. Each class that owns child classes needs to overload the procedure
- GetChildren. Within this procedure is needs to call the procedure passed as
- an argument for each child to be stored.
-
- Getting the objects out of the stream is a little trickier. Your parent
- object may need to overload the GetChildOwner and GetChildParent functions.
- Otherwise Delphi will try to make the child owned by the form.
-
-
- ------------------------------------------------------------------------
- Copyright 1996 - John Miano
-
- Contributers
-
- Glen Boyd